package com.forte.fortePoiUtils.writer.XSSFWriter;

import java.io.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.forte.fortePoiUtils.commons.Datas;
import com.forte.fortePoiUtils.writer.ExcelWriter;

/**
 * 扩展名.xlsx的excel表格写入助手
 * @author ForteScarlet
 * <div>
 *		<ul>
 *  		<li> ---><a href='https://gitee.com/ForteScarlet' target='_block'>码云个人地址</a></li> </li>
 *		</ul>
 * </div>
 */
public class XSSFWriter extends ExcelWriter {


	/**
	 * 构造方法
	 * @param filePath
	 * @param fileName
	 * @throws FileNotFoundException
	 */
	public XSSFWriter(String filePath, String fileName) throws FileNotFoundException {
		super(filePath, fileName);
	}

	/**
	 * 构造方法
	 * @param filePath
	 * @throws FileNotFoundException
	 */
	public XSSFWriter(File filePath) throws FileNotFoundException {
		super(filePath);
	}

	/**
	 * 构造方法
	 * @param outputStream
	 */
	public XSSFWriter(OutputStream outputStream) {
		super(outputStream);
	}

	/**
	 * 写入Excel方法，内部为了防止内存溢出，当字段数 * （对象数量 + 1） 时，将会使用SXSSFWorkbook对象进行写入，否则将会使用XSSFWorkbook对象进行写入
	 */
	@Override
	public <T> boolean writeToFile(List<T> objects, Map<String, String> result, Comparator<String> comparator, String sheetName, int startRow,	int startCol) throws IOException {
		//如果长度为0,结束方法
		if(objects.size() == 0)
			return false;

		//获取第一个对象,用于获取字段名称列表和类名
		T t = objects.get(0);
		List<String> fieldNames = Datas.getFieldsNameWithGetter(t);

		//如果映射（result）不为空，将仅保留映射中存在的字段 - 将Map中的key转化为字段list集合
		if(result != null){
			fieldNames = result.entrySet().stream().map(set -> set.getKey()).collect(Collectors.toList());
		}

//		Datas.filteField(t.getClass() , fieldNames , result);
//		fieldNames = fieldNames.stream().filter(name -> {
//			try {
//				return Datas.isFieldExist(t , name);
//			} catch (NoSuchFieldException e) {
//				e.printStackTrace();
//				return false;
//			}
//		}).collect(Collectors.toList());


		//如果表名为空，则使用类名代替
		if(sheetName == null)
			sheetName = Datas.getClassName(t);
			
		/*
		 * 创建工作簿 - 根据集合大小决定创建何种类型
		 * 计算一下预计的Cell对象创建数量
		 * 创建数量 ： 字段数 * （对象数量 + 1）
		 * 如果数量超过100000
		 */
		long cellNumber = fieldNames.size() * (1 + objects.size());
		//对象数量临界值
		long up = 100000;
		
		//获取工作簿对象
		Workbook book;
		
		if(cellNumber >= up)
			book = new SXSSFWorkbook();
		else
			book = new XSSFWorkbook();
		
		
		
		//获取表格
		Sheet sheet = book.createSheet(sheetName);
		
		//如果有排序接口，进行排序
		if(comparator != null)
			Collections.sort(fieldNames , comparator);
		
		//先写入字段名称 - 表头
		//获取标头一行
		Row tableHeadRow = sheet.createRow( startRow++ );
		for(int i = startCol,index = 0; i < startCol + fieldNames.size() && index < fieldNames.size(); i++ , index++){
			String headData = fieldNames.get(index);
			tableHeadRow.createCell(i).setCellValue((result == null || result.get(headData) == null) ? headData : result.get(headData));
		}
		
		//再写入其他数据 - 遍历objects
		for(T o : objects){
			//一行
			Row row = sheet.createRow( startRow++ );
			//根据字段数量循环
			for(int i = startCol,index = 0; i < startCol + fieldNames.size() && index < fieldNames.size(); i++ , index++){
				try{
					row.createCell(i).setCellValue(Datas.objectGetter(o, fieldNames.get(index)).toString());
				}catch(Exception e){
					System.err.println("数据添加出现异常");
					e.printStackTrace();
					return false;
				}
			}
		}
		//数据全部写入完成,输出至硬盘中
//		FileOutputStream out = new FileOutputStream(getFile());
		book.write(getOutPutStream());
		//关流
		streamClose();
		return true;
	}

}
